package com.example.lxx;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

// 定义用户角色
enum Role {
    S, // 系统管理员
    M, // 店长
    T, // 售票员
    C  // 顾客
}

// 用户类
class User {
    private final String username;
    private final Role role;

    public User(String username, Role role) {
        this.username = username;
        this.role = role;
    }

    public Role getRole() {
        return role;
    }

    public String getUsername() {
        return username;
    }
}

// 权限控制类
class PermissionControl {
    private Role role;

    public PermissionControl(Role role) {
        this.role = role;
    }

    // 只有售票员（T）有权限购票
    public boolean canProcessTicket() {
        return role == Role.T;
    }

    // 系统管理员（S）和店长（M）可以管理影厅和排片
    public boolean canManageHalls() {
        return role == Role.S || role == Role.M;
    }
}

// 电影院类
class Cinema {
    private String name;
    private List<Hall> halls;
    private List<Schedule> schedules;

    public Cinema(String name) {
        this.name = name;
        this.halls = new ArrayList<>();
        this.schedules = new ArrayList<>();
        initializeDefaultSchedules(); // 初始化默认排片
    }

    // 初始化默认排片（至少1条）
    private void initializeDefaultSchedules() {
        // 添加影厅
        Hall hall1 = new Hall(1, 5, 10);
        Hall hall2 = new Hall(2, 8, 12);
        halls.add(hall1);
        halls.add(hall2);

        // 添加默认排片（明天及后天）
        LocalDateTime tomorrow = LocalDateTime.now().plusDays(1);
        LocalDateTime dayAfterTomorrow = LocalDateTime.now().plusDays(2);

        addSchedule("三体", hall1, tomorrow.withHour(14).withMinute(0));
        addSchedule("流浪地球", hall2, tomorrow.withHour(16).withMinute(30));
        addSchedule("宇宙探索编辑部", hall1, dayAfterTomorrow.withHour(19).withMinute(0));
    }

    public void addHall(Hall hall) {
        halls.add(hall);
    }

    public void addSchedule(String movieName, Hall hall, LocalDateTime time) {
        schedules.add(new Schedule(movieName, hall, time));
    }

    public List<Schedule> findSchedulesByMovieName(String movieName) {
        List<Schedule> result = new ArrayList<>();
        for (Schedule schedule : schedules) {
            if (schedule.getMovieName().equals(movieName)) {
                result.add(schedule);
            }
        }
        return result;
    }

    // 获取所有排片
    public List<Schedule> getAllSchedules() {
        return new ArrayList<>(schedules);
    }

    // Getter方法
    public String getName() { return name; }
    public List<Hall> getHalls() { return halls; }
    public List<Schedule> getSchedules() { return schedules; }
}

// 放映厅类
class Hall {
    private int id;
    private SeatMatrix seatMatrix;

    public Hall(int id, int rows, int cols) {
        this.id = id;
        this.seatMatrix = new SeatMatrix(rows, cols);
    }

    public void showSeatsStatus() {
        seatMatrix.showStatus();
    }

    // Getter方法
    public int getId() { return id; }
    public SeatMatrix getSeatMatrix() { return seatMatrix; }
}

// 排片类
class Schedule {
    private String movieName;
    private Hall hall;
    private LocalDateTime time;

    public Schedule(String movieName, Hall hall, LocalDateTime time) {
        this.movieName = movieName;
        this.hall = hall;
        this.time = time;
    }

    @Override
    public String toString() {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
        return movieName + " - 影厅:" + hall.getId() + " 时间:" + time.format(formatter);
    }

    // Getter方法
    public String getMovieName() { return movieName; }
    public Hall getHall() { return hall; }
    public LocalDateTime getTime() { return time; }
}

// 座位矩阵类
class SeatMatrix {
    private int rowCount;
    private int colCount;
    private String[][] seats;

    public SeatMatrix(int rowCount, int colCount) {
        this.rowCount = rowCount;
        this.colCount = colCount;
        this.seats = new String[rowCount][colCount];
        initializeSeats();
    }

    private void initializeSeats() {
        for (int i = 0; i < rowCount; i++) {
            for (int j = 0; j < colCount; j++) {
                seats[i][j] = "空"; // 初始化为空座位
            }
        }
    }

    public boolean setSeat(int row, int col, String userId) {
        if (isValidPosition(row, col) && isSeatAvailable(row, col)) {
            seats[row][col] = userId;
            return true;
        }
        return false;
    }

    public boolean releaseSeat(int row, int col) {
        if (isValidPosition(row, col) && !isSeatAvailable(row, col)) {
            seats[row][col] = "空";
            return true;
        }
        return false;
    }

    private boolean isSeatAvailable(int row, int col) {
        return "空".equals(seats[row][col]);
    }

    private boolean isValidPosition(int row, int col) {
        return row >= 0 && row < rowCount && col >= 0 && col < colCount;
    }

    public void showStatus() {
        System.out.print(" ");
        for (int j = 0; j < colCount; j++) {
            System.out.printf("%-4d", j + 1); // 打印列号
        }
        System.out.println();

        for (int i = 0; i < rowCount; i++) {
            System.out.printf("%2d ", i + 1); // 打印行号
            for (int j = 0; j < colCount; j++) {
                String status = "空".equals(seats[i][j]) ? "○" : "●";
                System.out.printf("%-4s", status);
            }
            System.out.println();
        }
        System.out.println("○: 空位 ●: 已售");
    }

    // Getter方法
    public int getRowCount() { return rowCount; }
    public int getColCount() { return colCount; }
    public String[][] getSeats() { return seats; }
}

// 用户管理类（直接使用枚举值作为角色显示名）
class UserManager {
    private static Map<String, User> users = new HashMap<>();

    // 初始化测试用户
    static {
        users.put("admin", new User("admin", Role.S));
        users.put("manager", new User("manager", Role.M));
        users.put("seller", new User("seller", Role.T));
        users.put("customer", new User("customer", Role.C));
    }

    // 验证用户登录
    public static User authenticate(String username, Role role) {
        User user = users.get(username);
        if (user == null) {
            System.out.println("用户不存在: " + username);
            return null;
        }
        if (user.getRole() != role) {
            System.out.println("角色不匹配 - 用户角色: " + user.getRole() + ", 输入角色: " + role);
            return null;
        }
        return user;
    }

    // 直接返回枚举值作为角色显示名
    public static String getRoleName(Role role) {
        return role.toString(); // 直接返回S/M/T/C
    }

    // 提供公共的访问方法来访问users
    public static Map<String, User> getUsers() {
        return users;
    }
}

// 主窗口类
class CinemaManagementSystemSwing {
    private Cinema cinema;
    private JFrame frame;
    private JPanel mainPanel;
    private JTextField movieSearchField;
    private JList<String> scheduleList;
    private JList<String> seatList;
    private JTextField rowField;
    private JTextField colField;
    private JTextField usernameField;
    private JComboBox<Role> roleComboBox;

    // 新增排片相关控件
    private JTextField newMovieNameField;
    private JComboBox<Integer> hallIdComboBox;
    private JTextField scheduleTimeField;

    // 当前登录用户
    private User currentUser;

    public CinemaManagementSystemSwing(User user) {
        this.currentUser = user;

        // 创建电影院（已包含默认排片）
        cinema = new Cinema("万达影城");

        // 初始化UI
        initializeUI();
    }

    private void initializeUI() {
        frame = new JFrame("电影院管理系统");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(800, 700);

        // 顶部显示当前用户信息
        JLabel userInfoLabel = new JLabel("当前用户: " + currentUser.getUsername() +
                " (角色: " + UserManager.getRoleName(currentUser.getRole()) + ")");
        userInfoLabel.setHorizontalAlignment(JLabel.RIGHT);

        mainPanel = new JPanel();
        mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));

        // 电影查询区域
        JPanel searchPanel = new JPanel();
        movieSearchField = new JTextField(20);
        JButton searchButton = new JButton("查询排片");
        searchButton.addActionListener(e -> refreshScheduleList());
        searchPanel.add(new JLabel("电影名:"));
        searchPanel.add(movieSearchField);
        searchPanel.add(searchButton);

        // 新增排片区域
        JPanel addSchedulePanel = new JPanel();
        addSchedulePanel.setBorder(BorderFactory.createTitledBorder("添加新排片"));

        newMovieNameField = new JTextField(10);
        hallIdComboBox = new JComboBox<>();
        // 初始化厅号下拉框
        for (Hall hall : cinema.getHalls()) {
            hallIdComboBox.addItem(hall.getId());
        }
        scheduleTimeField = new JTextField(15);
        scheduleTimeField.setToolTipText("格式: yyyy-MM-dd HH:mm");
        scheduleTimeField.setText(LocalDateTime.now().plusDays(1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd 15:00")));

        JButton addScheduleButton = new JButton("添加排片");
        addScheduleButton.addActionListener(e -> addNewSchedule());

        addSchedulePanel.add(new JLabel("电影名:"));
        addSchedulePanel.add(newMovieNameField);
        addSchedulePanel.add(new JLabel("厅号:"));
        addSchedulePanel.add(hallIdComboBox);
        addSchedulePanel.add(new JLabel("时间:"));
        addSchedulePanel.add(scheduleTimeField);
        addSchedulePanel.add(addScheduleButton);

        // 根据用户角色决定是否显示排片管理面板
        PermissionControl permission = new PermissionControl(currentUser.getRole());
        addSchedulePanel.setVisible(permission.canManageHalls());

        // 排片显示列表
        scheduleList = new JList<>();
        scheduleList.addListSelectionListener(e -> {
            if (!e.getValueIsAdjusting()) {
                updateSeatDisplay();
            }
        });
        JScrollPane scheduleScrollPane = new JScrollPane(scheduleList);
        scheduleScrollPane.setPreferredSize(new Dimension(800, 150));

        // 座位显示区域
        seatList = new JList<>();
        JScrollPane seatScrollPane = new JScrollPane(seatList);
        seatScrollPane.setPreferredSize(new Dimension(800, 300));

        // 购票区域
        JPanel ticketPanel = new JPanel();
        rowField = new JTextField(5);
        colField = new JTextField(5);
        usernameField = new JTextField(10);
        roleComboBox = new JComboBox<>(Role.values());
        roleComboBox.setSelectedItem(currentUser.getRole());

        // 使用自定义渲染器显示角色名称（直接显示S/M/T/C）
        roleComboBox.setRenderer(new DefaultListCellRenderer() {
            @Override
            public Component getListCellRendererComponent(JList<?> list, Object value, int index,
                                                          boolean isSelected, boolean cellHasFocus) {
                super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
                if (value instanceof Role) {
                    Role role = (Role) value;
                    setText(role.toString()); // 直接显示S/M/T/C
                }
                return this;
            }
        });

        JButton buyButton = new JButton("购票");
        buyButton.addActionListener(e -> processTicketPurchase());

        JButton resetButton = new JButton("重置");
        resetButton.addActionListener(e -> {
            rowField.setText("");
            colField.setText("");
        });

        ticketPanel.add(new JLabel("行号:"));
        ticketPanel.add(rowField);
        ticketPanel.add(new JLabel("列号:"));
        ticketPanel.add(colField);
        ticketPanel.add(new JLabel("用户名:"));
        ticketPanel.add(usernameField);
        ticketPanel.add(new JLabel("身份:"));
        ticketPanel.add(roleComboBox);
        ticketPanel.add(buyButton);
        ticketPanel.add(resetButton);

        // 添加所有组件到主面板
        mainPanel.add(userInfoLabel);
        mainPanel.add(searchPanel);
        mainPanel.add(addSchedulePanel);
        mainPanel.add(scheduleScrollPane);
        mainPanel.add(seatScrollPane);
        mainPanel.add(ticketPanel);

        frame.add(mainPanel);
        frame.setVisible(true);

        // 初始加载所有排片
        refreshScheduleList();
    }

    // 刷新排片列表
    private void refreshScheduleList() {
        String movieName = movieSearchField.getText().trim();
        List<Schedule> schedules;

        if (movieName.isEmpty()) {
            schedules = cinema.getAllSchedules();
        } else {
            schedules = cinema.findSchedulesByMovieName(movieName);
        }

        DefaultListModel<String> model = new DefaultListModel<>();
        for (int i = 0; i < schedules.size(); i++) {
            model.addElement((i + 1) + ". " + schedules.get(i));
        }
        scheduleList.setModel(model);
    }

    // 新增排片方法
    private void addNewSchedule() {
        try {
            String movieName = newMovieNameField.getText().trim();
            if (movieName.isEmpty()) {
                JOptionPane.showMessageDialog(frame, "请输入电影名称！");
                return;
            }

            // 检查权限
            PermissionControl permission = new PermissionControl(currentUser.getRole());
            if (!permission.canManageHalls()) {
                JOptionPane.showMessageDialog(frame, "权限不足！只有S和M角色可以添加排片。");
                return;
            }

            // 获取选择的厅
            int hallId = (int) hallIdComboBox.getSelectedItem();
            Hall selectedHall = null;
            for (Hall hall : cinema.getHalls()) {
                if (hall.getId() == hallId) {
                    selectedHall = hall;
                    break;
                }
            }
            if (selectedHall == null) {
                JOptionPane.showMessageDialog(frame, "未找到指定的放映厅！");
                return;
            }

            // 解析时间
            String timeStr = scheduleTimeField.getText().trim();
            LocalDateTime time;
            try {
                time = LocalDateTime.parse(timeStr, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
            } catch (DateTimeParseException ex) {
                JOptionPane.showMessageDialog(frame, "时间格式错误！请使用yyyy-MM-dd HH:mm格式。");
                return;
            }

            // 检查时间是否在当前时间之后
            if (time.isBefore(LocalDateTime.now())) {
                JOptionPane.showMessageDialog(frame, "排片时间必须在当前时间之后！");
                return;
            }

            // 添加排片
            cinema.addSchedule(movieName, selectedHall, time);
            JOptionPane.showMessageDialog(frame, "排片添加成功！");

            // 刷新排片列表
            refreshScheduleList();

            // 清空表单
            newMovieNameField.setText("");
            scheduleTimeField.setText(LocalDateTime.now().plusDays(1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd 16:00")));

        } catch (Exception ex) {
            JOptionPane.showMessageDialog(frame, "添加排片失败: " + ex.getMessage());
            ex.printStackTrace();
        }
    }

    // 更新座位显示
    private void updateSeatDisplay() {
        int selectedIndex = scheduleList.getSelectedIndex();
        if (selectedIndex < 0) {
            return;
        }

        List<Schedule> schedules = movieSearchField.getText().trim().isEmpty() ?
                cinema.getAllSchedules() : cinema.findSchedulesByMovieName(movieSearchField.getText().trim());

        if (selectedIndex >= schedules.size()) {
            return;
        }

        Schedule selectedSchedule = schedules.get(selectedIndex);
        Hall hall = selectedSchedule.getHall();
        SeatMatrix matrix = hall.getSeatMatrix();

        DefaultListModel<String> seatModel = new DefaultListModel<>();

        // 添加列标题行
        StringBuilder header = new StringBuilder(" ");
        for (int j = 0; j < matrix.getColCount(); j++) {
            header.append(String.format("%-4d", j + 1));
        }
        seatModel.addElement(header.toString());

        // 添加座位行
        for (int i = 0; i < matrix.getRowCount(); i++) {
            StringBuilder rowStr = new StringBuilder(String.format("%2d ", i + 1));
            for (int j = 0; j < matrix.getColCount(); j++) {
                String status = "空".equals(matrix.getSeats()[i][j]) ? "○" : "●";
                rowStr.append(String.format("%-4s", status));
            }
            seatModel.addElement(rowStr.toString());
        }

        seatModel.addElement("○: 空位 ●: 已售");
        seatList.setModel(seatModel);
    }

    // 购票处理方法
    private void processTicketPurchase() {
        try {
            int row = Integer.parseInt(rowField.getText());
            int col = Integer.parseInt(colField.getText());
            String username = usernameField.getText();

            if (username.isEmpty()) {
                JOptionPane.showMessageDialog(frame, "请输入用户名！");
                return;
            }

            int selectedIndex = scheduleList.getSelectedIndex();
            if (selectedIndex >= 0) {
                List<Schedule> schedules = movieSearchField.getText().trim().isEmpty() ?
                        cinema.getAllSchedules() : cinema.findSchedulesByMovieName(movieSearchField.getText().trim());
                Schedule selectedSchedule = schedules.get(selectedIndex);
                Hall hall = selectedSchedule.getHall();
                SeatMatrix matrix = hall.getSeatMatrix();

                // 权限检查（使用当前登录用户角色，而非选择的角色）
                PermissionControl permission = new PermissionControl(currentUser.getRole());
                if (!permission.canProcessTicket()) {
                    JOptionPane.showMessageDialog(frame, "权限不足！只有T角色可以购票。");
                    return;
                }

                // 检查座位是否超出范围
                if (row < 1 || row > matrix.getRowCount() || col < 1 || col > matrix.getColCount()) {
                    JOptionPane.showMessageDialog(frame, "无该座位！范围：1-" +
                            matrix.getRowCount() + "行，1-" + matrix.getColCount() + "列");
                    return;
                }

                if (matrix.setSeat(row - 1, col - 1, username)) {
                    updateSeatDisplay();
                    JOptionPane.showMessageDialog(frame, "售票成功！座位 (" + row +
                            "," + col + ") 已售出给 " + username);
                    // 保留用户名，清空座位号
                    rowField.setText("");
                    colField.setText("");
                } else {
                    JOptionPane.showMessageDialog(frame, "该座位已售出！");
                }
            } else {
                JOptionPane.showMessageDialog(frame, "请先选择排片！");
            }
        } catch (NumberFormatException ex) {
            JOptionPane.showMessageDialog(frame, "请输入有效的行号和列号！");
        }
    }

    // 登录窗口类
    static class LoginWindow {
        private JFrame loginFrame;
        private JTextField usernameField;
        private JComboBox<Role> roleComboBox;

        public LoginWindow() {
            initializeLoginUI();
        }

        private void initializeLoginUI() {
            loginFrame = new JFrame("系统登录");
            loginFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            loginFrame.setSize(300, 200);
            loginFrame.setLocationRelativeTo(null); // 居中显示

            JPanel panel = new JPanel();
            panel.setLayout(new GridLayout(4, 2, 10, 10));
            panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));

            JLabel usernameLabel = new JLabel("用户名:");
            usernameField = new JTextField();

            JLabel roleLabel = new JLabel("角色:");
            roleComboBox = new JComboBox<>(Role.values());

            // 使用自定义渲染器显示角色名称（直接显示S/M/T/C）
            roleComboBox.setRenderer(new DefaultListCellRenderer() {
                @Override
                public Component getListCellRendererComponent(JList<?> list, Object value, int index,
                                                              boolean isSelected, boolean cellHasFocus) {
                    super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
                    if (value instanceof Role) {
                        Role role = (Role) value;
                        setText(role.toString()); // 直接显示S/M/T/C
                    }
                    return this;
                }
            });

            JButton loginButton = new JButton("登录");
            loginButton.addActionListener(e -> attemptLogin());

            JButton cancelButton = new JButton("取消");
            cancelButton.addActionListener(e -> System.exit(0));

            panel.add(usernameLabel);
            panel.add(usernameField);
            panel.add(roleLabel);
            panel.add(roleComboBox);
            panel.add(new JLabel()); // 占位
            panel.add(new JLabel()); // 占位
            panel.add(loginButton);
            panel.add(cancelButton);

            loginFrame.add(panel);
            loginFrame.setVisible(true);
        }

        private void attemptLogin() {
            String username = usernameField.getText().trim();
            Role role = (Role) roleComboBox.getSelectedItem();

            if (username.isEmpty()) {
                JOptionPane.showMessageDialog(loginFrame, "请输入用户名！");
                return;
            }

            User user = UserManager.authenticate(username, role);
            if (user != null) {
                loginFrame.dispose(); // 关闭登录窗口
                new CinemaManagementSystemSwing(user); // 打开主界面
            } else {
                // 提供更详细的错误信息
                StringBuilder message = new StringBuilder("登录失败！\n\n");
                User storedUser = UserManager.getUsers().get(username);
                if (storedUser == null) {
                    message.append("用户名不存在！\n\n可用用户名：\n");
                    for (String name : UserManager.getUsers().keySet()) {
                        message.append("- ").append(name).append(" (")
                                .append(UserManager.getRoleName(UserManager.getUsers().get(name).getRole())).append(")\n");
                    }
                } else {
                    message.append("角色不匹配！\n");
                    message.append("用户名 '").append(username).append("' 的正确角色是：");
                    message.append(UserManager.getRoleName(storedUser.getRole())).append(" (")
                            .append(storedUser.getRole()).append(")");
                }
                JOptionPane.showMessageDialog(loginFrame, message.toString(), "登录错误", JOptionPane.ERROR_MESSAGE);
            }
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(LoginWindow::new);
    }
}
